package com.example.androidproject.service;

import android.app.Notification;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;

import androidx.annotation.Nullable;

import com.hyg.base.ui.base.BaseActivity;

import java.util.Calendar;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * FileName: TimersService
 * Author: huangyuguang
 * Date: 2022/5/12
 * Description: app程序进入后台或者手机屏幕关闭，开启的定时器任务（使用timers的计数任务）继续执行
 *
 * 保持Android Service在手机休眠后继续运行
 * https://blog.csdn.net/sinat_33285127/article/details/76131349
 */
public class TimersService extends Service {
    private final static String TAG = TimersService.class.getSimpleName();

    private final static int GRAY_SERVICE_ID = 1001;

    private int heartBeat1 = 0;
    private int heartBeat2 = 0;

    private TimersClientBinder mBinder = new TimersClientBinder();

    private PowerManager.WakeLock mWakeLock = null;

    //用于Activity和service通讯
    public class TimersClientBinder extends Binder {
        public TimersService getService() {
            return TimersService.this;
        }
    }

    //Android4.3 - Android8.0 灰色保活
    public static class GrayInnerService extends Service {

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            startForeground(GRAY_SERVICE_ID, new Notification());
            stopForeground(true);
            stopSelf();
            return super.onStartCommand(intent, flags, startId);
        }

        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
//        getLock();
    }

    @Override
    public int onStartCommand(Intent intent,int flags, int startId) {
        getLock();
        mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测
        daemonThread();

        //设置service为前台服务，提高优先级
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
            //Android4.3以下 ，隐藏Notification上的图标
            startForeground(GRAY_SERVICE_ID, new Notification());
        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            //Android4.3 - Android8.0，隐藏Notification上的图标
            Intent innerIntent = new Intent(this, GrayInnerService.class);
            startService(innerIntent);
            startForeground(GRAY_SERVICE_ID, new Notification());
        } else {
            //Android8.0以上app启动后通知栏会出现一条"正在运行"的通知
            /*NotificationChannel channel = new NotificationChannel("1", "yt-live-sdk",
                    NotificationManager.IMPORTANCE_HIGH);
            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            if (manager != null) {
                manager.createNotificationChannel(channel);
                Notification notification = new Notification.Builder(getApplicationContext(), "1").build();
                startForeground(GRAY_SERVICE_ID, notification);
            }*/
        }

        //START_STICKY: 被杀后自动重启，保持启动状态，不保持Intent，重新调用onStartCommand，无新Intent则为空Intent—杀死重启后，不继续执行先前任务，能接受新任务
        //START_NOT_STICKY: 被杀后不重启，不保持启动状态，可以随时停止，适合定时数据轮询场景
        //START_REDELIVER_INTENT: 如果有未处理完的Intent，被杀后会重启，并在重启后发送所有Intent。stopSelf后释放保持的Intent。
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        releaseLock();
        cancelTimer();
        compositeDisposable.clear();
        super.onDestroy();
    }

    synchronized public void startTimer(){
        mHandler.removeCallbacks(heartBeatRunnable);
        mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳检测
    }

    synchronized public void cancelTimer(){
        if(mHandler != null && heartBeatRunnable != null){
            mHandler.removeCallbacks(heartBeatRunnable);
        }
    }

    /**
     * 同步方法   得到休眠锁，保持cpu唤醒
     * 这个API会加剧耗电，所以在非必要情况下尽量不要使用。如果要使用尽量使用最低的等级，并在退出后释放资源。
     */
    synchronized private void getLock(){
        if(mWakeLock==null){
            PowerManager mgr=(PowerManager)getSystemService(Context.POWER_SERVICE);
            mWakeLock=mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TimersService.class.getName());
            mWakeLock.setReferenceCounted(true);
            Calendar c= Calendar.getInstance();
            c.setTimeInMillis((System.currentTimeMillis()));
            int hour =c.get(Calendar.HOUR_OF_DAY);
            if(hour>=23||hour<=6){
                //当超过timeOut之后系统自动释放WakeLock。
                mWakeLock.acquire(5000);
            }else{
                mWakeLock.acquire(300000);
            }
        }
    }

    synchronized private void releaseLock()
    {
        if(mWakeLock!=null){
            if(mWakeLock.isHeld()) {
                mWakeLock.release();
            }
            mWakeLock=null;
        }
    }

    //    -------------------------------------Handler定时任务------------------------------------------------
    private static final long HEART_BEAT_RATE = 10 * 1000;//每隔10秒进行一次对长连接的心跳检测
    private Handler mHandler = new Handler();
    private Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            //do somathing
            //每隔一定的时间，对长连接进行一次心跳检测
            mHandler.postDelayed(this, HEART_BEAT_RATE);

            heartBeat1 ++;
            heartBeat2 = 0;
            if(heartBeat1 > 2){//daemonThreadDisposable 已经很久没给heartBeat1清零了，估计死了
                heartBeat1 = 0;
                try {
                    daemonThreadDisposable.dispose();
                }catch (Exception e){}
                daemonThreadDisposable = null;
                daemonThread();
            }
        }
    };

    //------------------------------rxjava定时任务------------------------------------------------------------------------
    private CompositeDisposable compositeDisposable = new CompositeDisposable();
    private Disposable daemonThreadDisposable;//监听整个APP有没有完全退出
    /**
     * 守护线程，每隔10s检查一次app有没有完全退出
     */
    public void daemonThread() {
        if(daemonThreadDisposable == null || daemonThreadDisposable.isDisposed()){
            // initialDelay：首次执行任务延迟多少 period：定时任务时间间隔 unit：时间单位
            daemonThreadDisposable = Observable.interval(20, 10, TimeUnit.SECONDS)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Long>() {
                        @Override
                        public void accept(Long aLong) throws Exception {
                            if(BaseActivity.mActivities == null || BaseActivity.mActivities.size() == 0){
                                stopSelf();
                                return;
                            }

                            heartBeat1 = 0;
                            heartBeat2 ++;
                            if(heartBeat2 > 2){//heartBeatRunnable 已经很久没给heartBeat2清零了，估计死了
                                heartBeat2 = 0;
                                startTimer();
                            }
                        }
                    });
            compositeDisposable.add(daemonThreadDisposable);
        }
    }
}
